From d854d0b3a23a321925f982377119f9ec17cdb63f Mon Sep 17 00:00:00 2001 From: "emellor@ewan" Date: Mon, 19 Sep 2005 14:19:22 +0100 Subject: [PATCH] Revert accidental commit. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 17 +- tools/python/xen/xend/XendDomainInfo.py | 575 ++++++++++-------------- tools/python/xen/xend/image.py | 22 +- 3 files changed, 271 insertions(+), 343 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index e85dac37a5..e835ea9063 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -275,7 +275,8 @@ class XendDomain: @param config: configuration @return: domain """ - return XendDomainInfo.create(self.dbmap.getPath(), config) + dominfo = XendDomainInfo.create(self.dbmap, config) + return dominfo def domain_restart(self, dominfo): """Restart a domain. @@ -308,7 +309,8 @@ class XendDomain: @param vmconfig: vm configuration """ config = sxp.child_value(vmconfig, 'config') - return XendDomainInfo.restore(self.dbmap.getPath(), config) + dominfo = XendDomainInfo.restore(self.dbmap, config) + return dominfo def domain_restore(self, src, progress=False): """Restore a domain from file. @@ -350,12 +352,13 @@ class XendDomain: dompath = self.domroot log.info("Creating entry for unknown xend domain: id=%d uuid=%s", dom0, uuid) + db = self.dbmap.addChild("%s/xend" % uuid) try: - dominfo = XendDomainInfo.recreate(uuid, dompath, info) - except Exception, exn: - log.exception(exn) - raise XendError("Error recreating xend domain info: id=%d: %s" % - (dom0, str(exn))) + dominfo = XendDomainInfo.recreate(uuid, dompath, dom0, + db, info) + except: + raise XendError("Error recreating xend domain info: id=%d" % + dom0) self._add_domain(dominfo) return dominfo diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 34014de31d..f26323cb94 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -136,179 +136,123 @@ class XendDomainInfo: """ MINIMUM_RESTART_TIME = 20 - - def create(cls, parentdbpath, config): + def create(cls, parentdb, config): """Create a VM from a configuration. - @param parentdbpath: parent db path + @param parentdb: parent db @param config configuration @raise: VmError for invalid configuration """ + uuid = getUuid() + db = parentdb.addChild("%s/xend" % uuid) + path = parentdb.getPath() + vm = cls(uuid, path, db) + vm.construct(config) + vm.saveToDB(sync=True) - log.debug("XendDomainInfo.create(%s, ...)", parentdbpath) - - vm = cls(getUuid(), parentdbpath, cls.parseConfig(config)) - vm.construct() return vm create = classmethod(create) - - def recreate(cls, uuid, dompath, info): + def recreate(cls, uuid, path, domid, db, info): """Create the VM object for an existing domain. - @param dompath: The path to all domain information + @param db: domain db @param info: domain info from xc """ + vm = cls(uuid, path, db) + vm.setDomid(domid) + vm.name, vm.start_time = vm.gatherVm(("name", str), + ("start-time", float)) + try: + db.readDB() + except: pass + vm.importFromDB() + config = vm.config + log.debug('info=' + str(info)) + log.debug('config=' + prettyprintstring(config)) - log.debug("XendDomainInfo.recreate(%s, %s, ...)", uuid, dompath) - - # ??? vm.setDomid(domid) -# vm.name, vm.start_time = vm.gatherVm(("name", str), -# ("start-time", float)) -# config = vm.config -# log.debug('info=' + str(info)) -# log.debug('config=' + prettyprintstring(config)) - -# vm.memory = info['mem_kb'] / 1024 -# vm.target = info['mem_kb'] * 1024 - + vm.memory = info['mem_kb'] / 1024 + vm.target = info['mem_kb'] * 1024 - # Parse the configuration in the store, but allow the info we've - # been given (from xc) to override it. - path = "%s/%s" % (dompath, uuid) - - config = xstransact.Read(path, 'config') if config: - temp_info = cls.parseConfig(config) - temp_info.update(info) - info = temp_info - - return cls(uuid, dompath, info) + try: + vm.recreate = True + vm.construct(config) + finally: + vm.recreate = False + else: + vm.setName("Domain-%d" % domid) - recreate = classmethod(recreate) + vm.exportToDB(save=True) + return vm + recreate = classmethod(recreate) - def restore(cls, parentdbpath, config, uuid = None): + def restore(cls, parentdb, config, uuid=None): """Create a domain and a VM object to do a restore. - @param parentdbpath: parent db + @param parentdb: parent db @param config: domain configuration @param uuid: uuid to use """ - - log.debug("XendDomainInfo.restore(%s, ..., %s)", parentdbpath, uuid) - if not uuid: uuid = getUuid() - - try: - ssidref = int(sxp.child_value(config, 'ssidref')) - except TypeError, exn: - raise VmError('Invalid ssidref in config: %s' % exn) - - log.debug('restoring with ssidref = %d' % ssidref) - - vm = cls(uuid, parentdbpath, cls.parseConfig(config), - xc.domain_create(ssidref = ssidref)) + db = parentdb.addChild("%s/xend" % uuid) + path = parentdb.getPath() + vm = cls(uuid, path, db) + ssidref = int(sxp.child_value(config, 'ssidref')) + log.debug('restoring with ssidref='+str(ssidref)) + id = xc.domain_create(ssidref = ssidref) + vm.setDomid(id) vm.clear_shutdown() + try: + vm.restore = True + vm.construct(config) + finally: + vm.restore = False + vm.exportToDB(save=True, sync=True) return vm restore = classmethod(restore) - - def parseConfig(cls, config): - def get_cfg(name, default = None): - return sxp.child_value(config, name, default) - - def int_get_cfg(name): - val = get_cfg(name) - if val: - return int(val) - else: - return None - - def flo_get_cfg(name): - val = get_cfg(name) - if val: - return float(val) - else: - return None - - - log.debug("parseConfig: config is %s" % str(config)) - - - result = {} - imagecfg = "()" - try: - result['name'] = get_cfg('name') - result['ssidref'] = int_get_cfg('ssidref') - result['memory'] = int_get_cfg('memory') - result['maxmem'] = int_get_cfg('maxmem') - result['cpu'] = int_get_cfg('cpu') - result['cpu_weight'] = flo_get_cfg('cpu_weight') - result['bootloader'] = get_cfg('bootloader') - result['restart_mode'] = get_cfg('restart') - - imagecfg = get_cfg('image') - - if imagecfg: - result['image'] = imagecfg - result['vcpus'] = int(sxp.child_value(imagecfg, 'vcpus', 1)) - else: - result['vcpus'] = 1 - - result['backend'] = [] - for c in sxp.children(config, 'backend'): - result['backend'].append(sxp.name(sxp.child0(c))) - - result['device'] = [] - for d in sxp.children(config, 'device'): - c = sxp.child0(d) - result['device'].append((sxp.name(c), c)) - - - log.debug("parseConfig: result is %s" % str(result)) - return result - - except TypeError, exn: - raise VmError( - 'Invalid ssidref / memory / cpu / cpu_weight / vcpus value: %s %s %s %s %s: %s' % - (get_cfg('ssidref'), - get_cfg('memory'), - get_cfg('cpu'), - get_cfg('cpu_weight'), - sxp.child_value(imagecfg, 'vcpus', 1), - str(exn))) - - parseConfig = classmethod(parseConfig) - + __exports__ = [ + DBVar('config', ty='sxpr'), + DBVar('state', ty='str'), + DBVar('restart_mode', ty='str'), + DBVar('restart_state', ty='str'), + DBVar('restart_time', ty='float'), + DBVar('restart_count', ty='int'), + ] - def __init__(self, uuid, parentpath, info, domid = None): - + def __init__(self, uuid, path, db): self.uuid = uuid - self.info = info + self.path = path + "/" + uuid - self.path = parentpath + "/" + uuid - - if domid: - self.domid = domid - elif 'dom' in info: - self.domid = int(info['dom']) - else: - self.domid = None - - self.validateInfo() + self.db = db + self.recreate = 0 + self.restore = 0 + + self.config = None + self.domid = None + self.cpu_weight = 1 self.start_time = None + self.name = None + self.memory = None + self.ssidref = None self.image = None + self.target = None + self.store_channel = None self.store_mfn = None self.console_channel = None self.console_mfn = None + self.info = None + self.backend_flags = 0 + #todo: state: running, suspended self.state = STATE_VM_OK self.state_updated = threading.Condition() @@ -317,69 +261,17 @@ class XendDomainInfo: #todo: set to migrate info if migrating self.migrate = None + self.restart_mode = RESTART_ONREBOOT self.restart_state = None self.restart_time = None self.restart_count = 0 - self.device_model_pid = 0 + self.vcpus = 1 + self.bootloader = None self.writeVm("uuid", self.uuid) self.storeDom("vm", self.path) - - def validateInfo(self): - """Validate and normalise the info block. This has either been parsed - by parseConfig, or received from xc through recreate. - """ - def defaultInfo(name, val): - if name not in self.info or self.info[name] is None: - self.info[name] = val() - - - try: - defaultInfo('name', lambda: "Domain-%d" % self.domid) - defaultInfo('memory', lambda: self.info['mem_kb'] / 1024) - defaultInfo('maxmem', lambda: self.info['memory']) - defaultInfo('restart_mode', lambda: RESTART_ONREBOOT) - defaultInfo('cpu_weight', lambda: 1.0) - defaultInfo('bootloader', lambda: None) - defaultInfo('backend', lambda: []) - defaultInfo('device', lambda: []) - - # vm.target = info['mem_kb'] * 1024 - - # !!! Consistency checks have the possibility of going wrong if - # xen updates us with a setting which should stay consistent with - # another. We should be storing only one value instead. - - # Validate the given backend names. - for s in self.info['backend']: - if s not in backendFlags: - raise VmError('Invalid backend type: %s' % s) - - for (n, c) in self.info['device']: - if not n or not c or n not in controllerClasses: - raise VmError('invalid device (%s, %s)' % - (str(n), str(c))) - - if self.info['restart_mode'] not in restart_modes: - raise VmError('invalid restart mode: ' + - str(self.info['restart_mode'])) - - if self.info['memory'] <= 0: - # !!! memory / mem_kb consistency check - raise VmError('Invalid memory size: %d', self.info['memory']) - - if 'cpumap' not in self.info: - if [self.info['vcpus'] == 1]: - self.info['cpumap'] = [1]; - else: - raise VmError('Cannot create CPU map') - - except KeyError, exn: - raise VmError('Unspecified domain detail: %s' % str(exn)) - - def readVm(self, *args): return xstransact.Read(self.path, *args) @@ -410,27 +302,18 @@ class XendDomainInfo: def storeDom(self, *args): return xstransact.Store(self.path, *args) + def setDB(self, db): + self.db = db - def exportToDB(self, save=False): - to_store = { - 'id': str(self.domid), - 'uuid': self.uuid, - 'config': sxp.to_string(self.sxpr()), - - 'start_time': str(self.start_time), - 'state': self.state, - 'restart_time': str(self.restart_time), - 'restart_count': str(self.restart_count), - 'device_model_pid': str(self.device_model_pid) - } - - for (k, v) in self.info.items(): - to_store[k] = str(v) - - log.debug("Storing %s" % str(to_store)) + def saveToDB(self, save=False, sync=False): + self.db.saveDB(save=save, sync=sync) - self.writeVm(to_store) + def exportToDB(self, save=False, sync=False): + self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync) + def importFromDB(self): + self.db.importFromDB(self, fields=self.__exports__) + self.store_channel = self.eventChannel("store/port") def setDomid(self, domid): """Set the domain id. @@ -444,11 +327,11 @@ class XendDomainInfo: return self.domid def setName(self, name): - self.info['name'] = name + self.name = name self.storeVm("name", name) def getName(self): - return self.info['name'] + return self.name def getPath(self): return self.path @@ -457,14 +340,14 @@ class XendDomainInfo: return self.uuid def getVCpuCount(self): - return self.info['vcpus'] + return self.vcpus def getSsidref(self): - return self.info['ssidref'] + return self.ssidref def getMemoryTarget(self): """Get this domain's target memory size, in MiB.""" - return self.info['memory'] + return self.memory def setStoreRef(self, ref): self.store_mfn = ref @@ -472,8 +355,7 @@ class XendDomainInfo: def getBackendFlags(self): - return reduce(lambda x, y: x | backendFlags[y], - self.info['backend'], 0) + return self.backend_flags def closeStoreChannel(self): @@ -497,19 +379,18 @@ class XendDomainInfo: def setMemoryTarget(self, target): self.storeDom("memory/target", target) - - def update(self, info = None): - """Update with info from xc.domain_getinfo(). + def update(self, info=None): + """Update with info from xc.domain_getinfo(). """ - - if not info: - info = dom_get(self.domid) - if not info: + if info: + self.info = info + else: + di = dom_get(self.domid) + if not di: return - - self.info.update(info) - self.validateInfo() - + self.info = di + self.memory = self.info['mem_kb'] / 1024 + self.ssidref = self.info['ssidref'] def state_set(self, state): self.state_updated.acquire() @@ -517,7 +398,7 @@ class XendDomainInfo: self.state = state self.state_updated.notifyAll() self.state_updated.release() - self.exportToDB() + self.saveToDB() def state_wait(self, state): self.state_updated.acquire() @@ -528,9 +409,9 @@ class XendDomainInfo: def __str__(self): s = " Created domain=%d name=%s memory=%d', - self.domid, self.info['name'], self.info['memory']) - + self.setName(sxp.child_value(config, 'name')) + self.check_name(self.name) + self.init_image() + self.configure_cpus(config) + self.init_domain() self.register_domain() # Create domain devices. + self.configure_backends() + self.configure_restart() self.construct_image() self.configure() self.exportToDB(save=True) @@ -711,12 +559,41 @@ class XendDomainInfo: xd._add_domain(self) self.exportToDB(save=True) + def configure_cpus(self, config): + try: + self.cpu_weight = float(sxp.child_value(config, 'cpu_weight', '1')) + except: + raise VmError('invalid cpu weight') + self.memory = int(sxp.child_value(config, 'memory')) + if self.memory is None: + raise VmError('missing memory size') + self.setMemoryTarget(self.memory * (1 << 20)) + self.ssidref = int(sxp.child_value(config, 'ssidref')) + cpu = sxp.child_value(config, 'cpu') + if self.recreate and self.domid and cpu is not None and int(cpu) >= 0: + xc.domain_pincpu(self.domid, 0, 1< Created domain=%d name=%s memory=%d', + id, self.name, self.memory) + self.setDomid(id) + def eventChannel(self, path=None): """Create an event channel to the domain. @@ -837,8 +731,14 @@ class XendDomainInfo: self.console_channel = self.eventChannel("console/port") def create_configured_devices(self): - for (n, c) in self.info['device']: - self.createDevice(n, c) + devices = sxp.children(self.config, 'device') + for d in devices: + dev_config = sxp.child0(d) + if dev_config is None: + raise VmError('invalid device') + dev_type = sxp.name(dev_config) + + self.createDevice(dev_type, dev_config) def create_devices(self): @@ -870,6 +770,14 @@ class XendDomainInfo: self.configureDevice(deviceClass, devid, dev_config) + def configure_restart(self): + """Configure the vm restart mode. + """ + r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT) + if r not in restart_modes: + raise VmError('invalid restart mode: ' + str(r)) + self.restart_mode = r; + def restart_needed(self, reason): """Determine if the vm needs to be restarted when shutdown for the given reason. @@ -877,11 +785,11 @@ class XendDomainInfo: @param reason: shutdown reason @return True if needs restart, False otherwise """ - if self.info['restart_mode'] == RESTART_NEVER: + if self.restart_mode == RESTART_NEVER: return False - if self.info['restart_mode'] == RESTART_ALWAYS: + if self.restart_mode == RESTART_ALWAYS: return True - if self.info['restart_mode'] == RESTART_ONREBOOT: + if self.restart_mode == RESTART_ONREBOOT: return reason == 'reboot' return False @@ -913,7 +821,7 @@ class XendDomainInfo: tdelta = tnow - self.restart_time if tdelta < self.MINIMUM_RESTART_TIME: self.restart_cancel() - msg = 'VM %s restarting too fast' % self.info['name'] + msg = 'VM %s restarting too fast' % self.name log.error(msg) raise VmError(msg) self.restart_time = tnow @@ -932,13 +840,14 @@ class XendDomainInfo: self.exportToDB() self.restart_state = STATE_RESTART_BOOTING self.configure_bootloader() - self.construct() - self.exportToDB() + self.construct(self.config) + self.saveToDB() finally: self.restart_state = None def configure_bootloader(self): - if not self.info['bootloader']: + self.bootloader = sxp.child_value(self.config, "bootloader") + if not self.bootloader: return # if we're restarting with a bootloader, we need to run it # FIXME: this assumes the disk is the first device and @@ -949,13 +858,30 @@ class XendDomainInfo: if dev: disk = sxp.child_value(dev, "uname") fn = blkdev_uname_to_file(disk) - blcfg = bootloader(self.info['bootloader'], fn, 1, self.info['vcpus']) + blcfg = bootloader(self.bootloader, fn, 1, self.vcpus) if blcfg is None: msg = "Had a bootloader specified, but can't find disk" log.error(msg) raise VmError(msg) self.config = sxp.merge(['vm', ['image', blcfg]], self.config) + def configure_backends(self): + """Set configuration flags if the vm is a backend for netif or blkif. + Configure the backends to use for vbd and vif if specified. + """ + for c in sxp.children(self.config, 'backend'): + v = sxp.child0(c) + name = sxp.name(v) + if name == 'blkif': + self.backend_flags |= SIF_BLK_BE_DOMAIN + elif name == 'netif': + self.backend_flags |= SIF_NET_BE_DOMAIN + elif name == 'usbif': + pass + elif name == 'tpmif': + self.backend_flags |= SIF_TPM_BE_DOMAIN + else: + raise VmError('invalid backend type:' + str(name)) def configure(self): """Configure a vm. @@ -973,16 +899,19 @@ class XendDomainInfo: """ return - def configure_maxmem(self): - xc.domain_setmaxmem(self.domid, - maxmem_kb = self.info['maxmem'] * 1024) + try: + maxmem = int(sxp.child_value(self.config, 'maxmem', self.memory)) + xc.domain_setmaxmem(self.domid, maxmem_kb = maxmem * 1024) + except: + raise VmError("invalid maxmem: " + + sxp.child_value(self.config, 'maxmem')) def vcpu_hotplug(self, vcpu, state): """Disable or enable VCPU in domain. """ - if vcpu > self.info['vcpus']: + if vcpu > self.vcpus: log.error("Invalid VCPU %d" % vcpu) return if int(state) == 0: @@ -1071,24 +1000,16 @@ implements the device control specific to that device-class.""" controllerClasses = {} -"""A map of backend names and the corresponding flag.""" -backendFlags = {} - - -def addControllerClass(device_class, backend_name, backend_flag, cls): +def addControllerClass(device_class, cls): """Register a subclass of DevController to handle the named device-class. - - @param backend_flag One of the SIF_XYZ_BE_DOMAIN constants, or None if - no flag is to be set. """ cls.deviceClass = device_class - backendFlags[backend_name] = backend_flag controllerClasses[device_class] = cls from xen.xend.server import blkif, netif, tpmif, pciif, usbif -addControllerClass('vbd', 'blkif', SIF_BLK_BE_DOMAIN, blkif.BlkifController) -addControllerClass('vif', 'netif', SIF_NET_BE_DOMAIN, netif.NetifController) -addControllerClass('vtpm', 'tpmif', SIF_TPM_BE_DOMAIN, tpmif.TPMifController) -addControllerClass('pci', 'pciif', None, pciif.PciController) -addControllerClass('usb', 'usbif', None, usbif.UsbifController) +addControllerClass('vbd', blkif.BlkifController) +addControllerClass('vif', netif.NetifController) +addControllerClass('vtpm', tpmif.TPMifController) +addControllerClass('pci', pciif.PciController) +addControllerClass('usb', usbif.UsbifController) diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 17eae3e3d0..6d7f363ffd 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -145,21 +145,22 @@ class ImageHandler: except OSError, ex: log.warning("error removing bootloader file '%s': %s", f, ex) - def initDomain(self, dom, memory, ssidref, cpu, cpu_weight, bootloading): + def initDomain(self, dom, memory, ssidref, cpu, cpu_weight): """Initial domain create. @return domain id """ mem_kb = self.getDomainMemory(memory) - dom = xc.domain_create(dom = dom or 0, ssidref = ssidref) - # if bootloader, unlink here. But should go after buildDomain() ? - if bootloading: - self.unlink(self.kernel) - self.unlink(self.ramdisk) - if dom <= 0: - raise VmError('Creating domain failed: name=%s' % - self.vm.getName()) + if not self.vm.restore: + dom = xc.domain_create(dom = dom or 0, ssidref = ssidref) + # if bootloader, unlink here. But should go after buildDomain() ? + if self.vm.bootloader: + self.unlink(self.kernel) + self.unlink(self.ramdisk) + if dom <= 0: + raise VmError('Creating domain failed: name=%s' % + self.vm.getName()) log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom) xc.domain_setcpuweight(dom, cpu_weight) xc.domain_setmaxmem(dom, mem_kb) @@ -183,6 +184,9 @@ class ImageHandler: def createDomain(self): """Build the domain boot image. """ + if self.vm.recreate or self.vm.restore: + return + # Set params and call buildDomain(). self.flags = self.vm.getBackendFlags() -- 2.30.2